#include "buzzercontroller.h"
#include <qjson/parser.h>
#include <QFile>
#include <QDebug>
#include <QVariant>
#include <QDir>
#include <QDateTime>
#include <QTime>

BuzzerController::BuzzerController(const QString &configFile, QObject *parent) :
    QObject(parent)
{
    QFile file(configFile);
    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "BuzzerController: can't open config file";
        return;
    }

    QJson::Parser jParser;
    bool ok;
    m_config = jParser.parse(&file, &ok).toMap();
    if (!ok) {
        qWarning() << "can't parse config!";
        return;
    }

    QVariantList schedule = m_config["schedule"].toList();
    for (int i = 0; i < schedule.count(); ++i) {
        QVariantMap scheduleEntry = schedule.at(i).toMap();
        QTime t = scheduleEntry.value("time", QTime(0, 0, 0)).toTime();
        QString m = scheduleEntry.value("melody", "default").toString();
        m_schedule.append(qMakePair(t, m));
    }
    m_scheduleTimer = new QTimer(this);
    m_scheduleTimer->setSingleShot(true);
    connect(m_scheduleTimer, SIGNAL(timeout()),
            this, SLOT(scheduleTimeout()));
    initSchedule();

    m_player = new AudioPlayer(this);

    m_fsWatcher = new QFileSystemWatcher(this);
    qDebug() << "watch dir:" << m_config["auto_play_dir"].toString();
    m_fsWatcher->addPath(m_config["auto_play_dir"].toString());
    connect(m_fsWatcher, SIGNAL(directoryChanged(QString)),
            this, SLOT(autoPlayDirChange(QString)));
}

void BuzzerController::autoPlayDirChange(const QString &dirPath)
{
    QDir dir(dirPath);
    QStringList filesList = dir.entryList();
    if (filesList.count() > 2) {
        for(int i = 2; i < filesList.count(); ++i) {
            QString fileName = filesList.at(i);
            if (fileName.endsWith(".tmp"))
                continue;

            QString movedFile = QString("%1%2_%3")
                    .arg(m_config["old_played_dir"].toString())
                    .arg(QDateTime::currentDateTime().toString("MM.dd.yyyy_HH:mm:ss"))
                    .arg(fileName);
            if (dir.rename(filesList.at(2), movedFile)) {
                m_player->addAudio(movedFile);
            } else {
                qWarning() << "can't move" << fileName;
            }
        }

    }
}

void BuzzerController::scheduleTimeout()
{
    QString melody = m_schedule.at(m_scheduleIndex).second == "default" ?
                m_config["default_melody"].toString() :
                m_schedule.at(m_scheduleIndex).second;

    if (!QFile(melody).exists())
        melody = m_config["default_melody"].toString();

    m_player->addAudio(melody);

    int secs;
    QTime time = QTime::currentTime();

    if ((QDate::currentDate().dayOfWeek() == 7) // sunday - no buzzer
            || (++m_scheduleIndex == m_schedule.count())) { //n ext day
        m_scheduleIndex = 0;
        secs = time.secsTo(QTime(23, 59, 59)) + 1;
        secs += QTime(0, 0, 0).secsTo(m_schedule.at(0).first);
    } else {
        QTime nextTime = m_schedule.at(m_scheduleIndex).first;
        secs = time.secsTo(nextTime);
    }
    qDebug() << "next secs" << secs;
    m_scheduleTimer->start(secs * 1000);
}

void BuzzerController::initSchedule()
{
    int count = m_schedule.count();
    if (count < 1) {
        qWarning() << "invalid schedule";
        return;
    }

    QTime time = QTime::currentTime();
    QTime last = m_schedule.at(count - 1).first;
    if (time >= last) {
        int secs = time.secsTo(QTime(23, 59, 59)) + 1;
        secs += QTime(0, 0, 0).secsTo(m_schedule.at(0).first);
        qDebug() << "next morning" << secs;
        m_scheduleTimer->start(secs * 1000);
        return;
    }

    QTime prev = QTime(0, 0, 0);
    QTime next;

    int i = 0;
    for (; i < m_schedule.count() - 1; ++i) {
        next = m_schedule[i].first;
        if ((time >= prev) && (time < next))
            break;
        prev = next;
    }
    m_scheduleIndex = i;

    int nextSecs = time.secsTo(m_schedule.at(i).first);
    qDebug() << "next secs" << nextSecs;
    m_scheduleTimer->start(nextSecs * 1000);
}
